Import cal3d

Class CalCoreSubmesh

	Field m_vectorVertex:CalVertex[]
	Field m_vectorTangentsEnabled:Bool[]
	Field m_vectorvectorTangentSpace:CalTangentSpace[][]'CalTangentSpace[]
	Field m_vectorvectorTextureCoordinate:CalTextureCoordinate[][]'CalTextureCoordinate[]
	Field m_vectorPhysicalProperty:CalPhysicalProperty[]
	Field m_vectorFace:CalFace[]
	Field m_vectorSpring:CalSpring[]
	Field m_vectorCoreSubMorphTarget:CalCoreSubMorphTarget[]
	Field m_coreMaterialThreadId:Int
	Field m_lodCount:Int
	
	Method getCoreMaterialThreadId:Int()
	
		Return m_coreMaterialThreadId
	
	End

	Method getFaceCount:Int()
		Return m_vectorFace.Length
	End
	
	Method getLodCount:Int()
		Return m_lodCount
	End
	
	Method getSpringCount:Int()
		Return m_vectorSpring.Length
	End
	
	Method getVectorFace:CalFace[]()
		Return m_vectorFace
	End
	
	Method getVectorPhysicalProperty:CalPhysicalProperty[]()
		Return m_vectorPhysicalProperty
	End
	
	Method getVectorSpring:CalSpring[]()
		Return m_vectorSpring
	End

	Method getVectorVectorTangentSpace:CalTangentSpace[][]()
	
		Return m_vectorvectorTangentSpace
	
	End
	
	Method getVectorVectorTextureCoordinate:CalTextureCoordinate[][]()
		Return m_vectorvectorTextureCoordinate
	End
	
	Method getVectorVertex:CalVertex[]()
		Return m_vectorVertex
	End
	
	Method getVertexCount:Int()
		Return m_vectorVertex.Length
	End
	
	Method isTangentsEnabled:Bool(mapId:Int)
		
		If mapId < 0 Or mapId >= m_vectorTangentsEnabled.Length then
			return false
		Endif
		
		return m_vectorTangentsEnabled[mapId]
	End
	
	Method enableTangents:Bool(mapId:Int, enabled:Bool)
		If mapId < 0 Or mapId >= m_vectorTangentsEnabled.Length then
			return false
		Endif
		
		m_vectorTangentsEnabled[mapId] = enabled
	
		If enabled = false
			m_vectorvectorTangentSpace[mapId] = New CalTangentSpace[0]
			return true
		Endif
	
		m_vectorvectorTangentSpace[mapId] = New CalTangentSpace[m_vectorVertex.Length]
	
		For Local tangentId = 0  To m_vectorvectorTangentSpace[mapId].Length-1
			m_vectorvectorTangentSpace[mapId][tangentId] = new CalTangentSpace
		Next
	
		For Local faceId = 0  To m_vectorFace.Length-1
			UpdateTangentVector(m_vectorFace[faceId].vertexId[0], m_vectorFace[faceId].vertexId[1], m_vectorFace[faceId].vertexId[2], mapId)
			UpdateTangentVector(m_vectorFace[faceId].vertexId[1], m_vectorFace[faceId].vertexId[2], m_vectorFace[faceId].vertexId[0], mapId)
			UpdateTangentVector(m_vectorFace[faceId].vertexId[2], m_vectorFace[faceId].vertexId[0], m_vectorFace[faceId].vertexId[1], mapId)
		next
	
		For Local tangentId=0 To m_vectorvectorTangentSpace[mapId].Length-1
			m_vectorvectorTangentSpace[mapId][tangentId].tangent.normalize()
		Next
	
		return true	
		
	
	End
	
	
	Method reserve:Bool(vertexCount:Int, textureCoordinateCount:Int, faceCount:Int, springCount:int)
	
		m_vectorVertex = New CalVertex[vertexCount]
		m_vectorTangentsEnabled = New Bool[textureCoordinateCount]
		m_vectorvectorTangentSpace = New CalTangentSpace[textureCoordinateCount][]
		m_vectorvectorTextureCoordinate = New CalTextureCoordinate[textureCoordinateCount][]
	
	
		For Local textureCoordinateId=0 To textureCoordinateCount-1
			m_vectorvectorTextureCoordinate[textureCoordinateId] = New CalTextureCoordinate[vertexCount]
	
			If m_vectorTangentsEnabled[textureCoordinateId] = True Then 'Does this even ever happen? how?
				m_vectorvectorTangentSpace[textureCoordinateId] = New CalTangentSpace[vertexCount]
			else
				m_vectorvectorTangentSpace[textureCoordinateId] = New CalTangentSpace[0]
			Endif
		next
	
		m_vectorFace = New CalFace[faceCount]
		m_vectorSpring = New CalSpring[springCount]
	
		' reserve the space for the physical properties if we have springs in the core submesh instance
		If springCount > 0 then
			m_vectorPhysicalProperty = New CalPhysicalProperty[vertexCount]
		Endif
		return true	
		
	
	End
	
	Method setCoreMaterialThreadId:Void(coreMaterialThreadId:Int)
	
		m_coreMaterialThreadId = coreMaterialThreadId
	
	End
	
	Method setFace:Bool(faceId:Int, face:CalFace)
		If faceId < 0 Or faceId >= m_vectorFace.Length then
			return false
		Endif
		
		m_vectorFace[faceId] = face
		return true	
			
	End
	
	Method setLodCount:Void(lodCount:Int)
		m_lodCount = lodCount
	End
	
	Method setPhysicalProperty:Bool(vertexId:Int, physicalProperty:CalPhysicalProperty)
	
		If vertexId < 0 Or vertexId >= m_vectorPhysicalProperty.Length then
			return false
		Endif
		
		m_vectorPhysicalProperty[vertexId] = physicalProperty
		return true	
	
	End
	
	Method setSpring:Bool(springId:Int, spring:CalSpring)
	
		If springId < 0 Or springId >= m_vectorSpring.Length then
			return false
		Endif
		
		m_vectorSpring[springId] = spring
		return true	
	
	End
	
	Method setTangentSpace:Bool(vertexId, textureCoordinateId, tangent:CalVector, crossFactor:Float)
	
		If vertexId < 0 Or vertexId >= m_vectorVertex.Length then
			Return False
		Endif
		
		If textureCoordinateId < 0 Or textureCoordinateId >= m_vectorvectorTextureCoordinate.Length then 
			Return False
		Endif
		
		If m_vectorTangentsEnabled[textureCoordinateId] = false then
			Return False
		endif
	
		'this.m_vectorvectorTangentSpace[textureCoordinateId][vertexId].tangent = tangent;
		If m_vectorvectorTangentSpace[textureCoordinateId][vertexId].tangent = Null Then
			m_vectorvectorTangentSpace[textureCoordinateId][vertexId].tangent = New CalVector(tangent)
		else
			m_vectorvectorTangentSpace[textureCoordinateId][vertexId].tangent.assign(tangent)
		Endif
		m_vectorvectorTangentSpace[textureCoordinateId][vertexId].crossFactor = crossFactor
	
		return true
	
	
	End
	
	
	Method setTextureCoordinate:Bool(vertexId:Int, textureCoordinateId:Int, textureCoordinate:CalTextureCoordinate)
	
		If textureCoordinateId < 0 Or textureCoordinateId >= m_vectorvectorTextureCoordinate.Length then
			Return False
		Endif
		If vertexId < 0 Or vertexId >= m_vectorvectorTextureCoordinate[textureCoordinateId].Length then
			Return False
		Endif
	
		m_vectorvectorTextureCoordinate[textureCoordinateId][vertexId] = textureCoordinate
		Return True	
		
	
	End

	Method setVertex:Bool(vertexId:Int, vertex:CalVertex)
	
		If vertexId < 0 Or vertexId >= m_vectorVertex.Length
			Return False
		Endif
	
		m_vectorVertex[vertexId] = vertex
		Return True
			
	
	End
	

	Method addCoreSubMorphTarget:Int(coreSubMorphTarget:CalCoreSubMorphTarget)
	
		local subMorphTargetId = m_vectorCoreSubMorphTarget.Length
		m_vectorCoreSubMorphTarget = m_vectorCoreSubMorphTarget.Resize(subMorphTargetId+1) '.push(coreSubMorphTarget)
		m_vectorCoreSubMorphTarget[subMorphTargetId] = coreSubMorphTarget
		Return subMorphTargetId	
	
	End
	
	
	Method getCoreSubMorphTarget:CalCoreSubMorphTarget(subMorphTargetId:Int)
	
		If subMorphTargetId < 0 Or subMorphTargetId >= m_vectorCoreSubMorphTarget.Length Then
			Return Null
		Endif
		
		Return m_vectorCoreSubMorphTarget[subMorphTargetId]	
			
	
	End
	
	
	Method getCoreSubMorphTargetCount:Int()
	
		Return m_vectorCoreSubMorphTarget.Length
	
	End
	
	
	Method getVectorCoreSubMorphTarget:CalCoreSubMorphTarget[]()
	
		Return m_vectorCoreSubMorphTarget
	
	End
	
	
	Method scale:Void(factor:Float)
	
		For Local vertexId=0 To m_vectorVertex.Length-1
			m_vectorVertex[vertexId].position.multScalarLocal(factor)
		next
	
		If m_vectorSpring.Length > 0 then
			' There is a problem when we resize and that there is
			' a spring system, I was unable to solve this
			' problem, so I disable the spring system
			' if the scale are too big
			If Abs(factor - 1) > 0.1 then
				m_vectorSpring = New CalSpring[0]
				m_vectorPhysicalProperty = New CalPhysicalProperty[0]
			Endif
		Endif	
	
	End
	

	Method UpdateTangentVector:Void(v0:Int, v1:Int, v2:Int, mapId:Int)
	
		Local vvtx:CalVertex[] = getVectorVertex()
		Local vtex:CalTextureCoordinate[] = m_vectorvectorTextureCoordinate[mapId]
	
		' Step 1. Compute the approximate tangent vector.
		Local du1:Float = vtex[v1].u - vtex[v0].u
		local dv1:Float = vtex[v1].v - vtex[v0].v
		local du2:Float = vtex[v2].u - vtex[v0].u
		local dv2:Float = vtex[v2].v - vtex[v0].v
	
		local prod1:Float = (du1*dv2-dv1*du2)
		local prod2:Float = (du2*dv1-dv2*du1)
		If Abs(prod1) < 0.000001 Or Abs(prod2) < 0.000001 Then
			Return
		Endif
	
		local x:Float = dv2 / prod1
		local y:Float = dv1 / prod2
	
		local vec1:CalVector = vectorSub(vvtx[v1].position, vvtx[v0].position)
		local vec2:CalVector = vectorSub(vvtx[v2].position, vvtx[v0].position)
		local tangent:CalVector = vec1.multScalarLocal(x).addLocal(vec2.multScalarLocal(y))
	
		' Step 2. Orthonormalize the tangent.
		Local component:Float = vectorDot(tangent, vvtx[v0].normal)
		tangent.subLocal(vectorScalarMult(vvtx[v0].normal, component))
		tangent.normalize()
	
		' Step 3: Add the estimated tangent to the overall estimate for the vertex.
		m_vectorvectorTangentSpace[mapId][v0].tangent.addLocal(tangent)	
	
	End

End Class



Class CalTextureCoordinate
	
	Field u:Float
	Field v:Float
	
	Method New()
		u = 0
		v = 0
	End
	
	Method New(uv:CalTextureCoordinate)
		
		u = uv.u
		v = uv.v
	End
	
	Method New(uu:Float,vv:Float)
	
		u = uu
		v = vv
	
	End
	

End Class


Class CalTangentSpace

	Field tangent:CalVector
	Field crossFactor:Float
	
	Method New()
		tangent = New CalVector()
		crossFactor = 0
	End
	
	Method New(t:CalVector,c:Float=0)
	
		tangent = New CalVector(t)
		crossFactor = c
	End
	
	Method New(xx:Float,yy:Float,zz:Float,c:Float=0)
	
		tangent = New CalVector(xx,yy,zz)
		crossFactor = c		
	
	End
	

End Class


Class CalInfluence

	Field boneId:Int
	Field weight:Float
	
	Method New()
		boneId = 0
		weight = 0
	End
	
	Method New(b:Int,w:Float)
	
		boneId = b
		weight = w
	
	End

End Class

Class CalPhysicalProperty

	Field weight:Float
	Field position:CalVector
	Field positionOld:CalVector
	Field force:CalVector
	
	Method New()
	
		weight = 0
		position = New CalVector()
		positionOld = New CalVector()
		force = New CalVector()	
					
	End
	
	Method New(w:Float)
	
		weight = w
	
	End
	
	Method New(p:CalVector,o:CalVector,f:CalVector,w:Float=0)

		weight = w
		position = p
		positionOld = o
		force = f	
		
	End
	

End Class

Class CalVertex

	Field position:CalVector
	Field normal:CalVector
	Field vectorInfluence:CalInfluence[]
	Field collapseId:Int
	Field faceCollapseCount:Int
	
	Method New()
		
		position = New CalVector()
		normal = New CalVector()
		vectorInfluence = New CalInfluence[0]
		collapseId = 0
		faceCollapseCount = 0
		
	End
	
	Method New(p:CalVector)
	
		position = New CalVector(p)
		normal = New CalVector()
		vectorInfluence = New CalInfluence[0]
		collapseId = 0
		faceCollapseCount = 0		
	
	End 	
	
	Method New(p:CalVector,n:CalVector)
	
		position = New CalVector(p)
		normal = New CalVector(n)
		vectorInfluence = New CalInfluence[0]
		collapseId = 0
		faceCollapseCount = 0		
	
	End 
	
	Method New(p:CalVector,n:CalVector,i:CalInfluence[],c:Int=0,fcc:Int=0)

		position = New CalVector(p)
		normal = New CalVector(n)
		vectorInfluence = i.Resize(i.Length) 'Should make a copy
		collapseId = c
		faceCollapseCount = fcc		
	
	End
	
	Method assign(xx:Float,yy:Float,zz:Float)
	
		position = New CalVector(xx,yy,zz)
	
	End

	Method assign(p:CalVector)
	
		position = New CalVector(p)
	
	
	End 	
	
End Class


Class CalFace

	Field vertexId:Int[3]
	
	Method New()
	
		vertexId[0] = 0
		vertexId[1] = 0
		vertexId[2] = 0
			
	End
	
	Method New(v1:Int,v2:Int,v3:Int)
	
		vertexId[0] = v1
		vertexId[1] = v2
		vertexId[2] = v3
	
	End
	
	Method New(f:CalFace)
	
		vertexId[0] = f.vertexId[0]
		vertexId[1] = f.vertexId[1]
		vertexId[2] = f.vertexId[2]	
	
	End
	
	Method New(vi:Int[])
	
		vertexId[0] = vi[0]
		vertexId[1] = vi[1]
		vertexId[2] = vi[2]		
	
	End
	

End Class


Class CalSpring

	Field vertexId:Int[2]
	Field springCoefficient:Float
	Field idleLength:Float
	
	Method New()
	
		vertexId[0] = 0
		vertexId[1] = 0
		springCoefficient = 0
		idleLength = 0
	
	End
	
	
	Method New(id0:Int,id1:Int,sc:Float=0,l:Float=0)
	
		vertexId[0] = id0
		vertexId[1] = id1
		springCoefficient = sc
		idleLength = l
			
	End
	
	Method New(id:Int[],sc:Float=0,l:Float=0)
	
		vertexId[0] = id[0]
		vertexId[1] = id[1]
		springCoefficient = sc
		idleLength = l			
	End	
	

End Class